#include "cledMatrix.h"
#include "UGUI/ugui.h"
#include "LCD/lcd.h"
#include "cledMatrixRGB.h"
#include "Curve/hsv.h"
#include <math.h>

#define  COLOR_RGB_RED       0xFFFF0000
#define  COLOR_RGB_GREEN     0xFF00FF00
#define  COLOR_RGB_YELLOW    0xFFFFFF00
#define  COLOR_RGB_BLUE      0xFF0000FF
//#define  COLOR_RGB_PURPLE    0xFFA020F0
#define  COLOR_RGB_PURPLE    0xFFFF00FF
#define  COLOR_RGB_CYAN      0xFF00FFFF
#define  COLOR_RGB_WHITE     0xFFFFFFFF
#define  COLOR_RGB_BLACK     0x00000000

static inline uint32_t rgb_mixture(const uint32_t color, const uint32_t next_color, const uint8_t mixture1)
{
    //int i;
    uint32_t rgb1=0, rgb2=0;
    uint32_t color1, color2;
    rgb2 = 0xFF000000;
    for(int i=0; i<24; i+=8)
    {
        color1 = (color>>i)&0xFF;
        color2 = (next_color>>i)&0xFF;
        //rgb1 = (color1*(255-mixture)+color2*mixture)>>8;
        rgb1 = (color2*(255-mixture1)+color1*mixture1+255)>>8;
        //rgb1 = (color1>>mixture)&0xFF+ (color2<<(8-mixture))&0xFF;
        rgb2 |= (rgb1<<i);
    }
    return rgb2;
}
static int color_to_color2(const uint8_t scale[], const uint8_t scale_len, int16_t &_grayscale, uint8_t &_mode, const int16_t gmin, const int16_t gmax, const uint8_t step, uint32_t &color, const uint32_t color2)
{
    uint32_t color_tmp=0;
    uint16_t red,green,blue;
    int ret = -1;
#if 0
    if(0==_mode) // color2 ++
    {
        //qDebug("[%s--%d] color[%08X %08X %08X]", __func__, __LINE__, color, color2, color_tmp, _grayscale);
        color_tmp = rgb_mixture(color2, 0x00000000, _grayscale);
        //qDebug("[%s--%d] color[%08X %08X %08X] gray:%3d", __func__, __LINE__, color, color2, color_tmp, _grayscale);
        _grayscale += step;
        if(_grayscale>=gmax) { _mode=1; _grayscale=gmax;}
        red = ((color_tmp>>16)&0xFF) + ((color>>16)&0xFF);
        green = ((color_tmp>>8)&0xFF) + ((color>>8)&0xFF);
        blue = ((color_tmp>>0)&0xFF) + ((color>>0)&0xFF);
        color_tmp = (color>>24)&0xFF;
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, color,  color_tmp);
        color_tmp = (color_tmp<<8) + (red&0xFF);
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, red,  color_tmp);
        color_tmp = (color_tmp<<8) + (green&0xFF);
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, green,  color_tmp);
        color_tmp = (color_tmp<<8) + (blue&0xFF);
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, blue,  color_tmp);
        //qDebug("[%s--%d] color[%08X %08X %08X] rgb[%04X %04X %04X] _grayscale[%3d] \r\n", __func__, __LINE__, color, color2, color_tmp, red, green, blue, _grayscale);
        color = color_tmp;
    }
    else // color --
    {
        color_tmp = rgb_mixture(color, 0x00000000, _grayscale);
        _grayscale -= step;
        if(_grayscale<=gmin) { _mode=0; _grayscale=gmin; ret = 0; }
        red = ((color_tmp>>16)&0xFF) + ((color2>>16)&0xFF);
        green = ((color_tmp>>8)&0xFF) + ((color2>>8)&0xFF);
        blue = ((color_tmp>>0)&0xFF) + ((color2>>0)&0xFF);
        color_tmp = (color>>24)&0xFF;
        color_tmp = (color_tmp<<8) + (red&0xFF);
        color_tmp = (color_tmp<<8) + (green&0xFF);
        color_tmp = (color_tmp<<8) + (blue&0xFF);
        color = color_tmp;
    }
#else
    //const uint8_t scale[] = {230, 204, 180, 153, 130, 102, 80, 51, 30, 0};
    //const uint8_t scale[] = {0, 45, 85, 170, 210, 255};
    //const uint8_t scale_len = sizeof(scale);
    if(0==_mode) // color2 ++
    {
        //qDebug("[%s--%d] color[%08X %08X %08X]", __func__, __LINE__, color, color2, color_tmp, _grayscale);
        if(_grayscale>=scale_len) _grayscale=scale_len-1;
        if(_grayscale<0) _grayscale=0;
        color_tmp = rgb_mixture(color2, 0x00000000, scale[_grayscale]);
        //qDebug("[%s--%d] color[%08X %08X %08X] gray:%3d", __func__, __LINE__, color, color2, color_tmp, _grayscale);
        _grayscale++;
        if(_grayscale>=(scale_len-1)) { _mode=1; _grayscale=scale_len-1;}
        red = ((color_tmp>>16)&0xFF) + ((color>>16)&0xFF);
        green = ((color_tmp>>8)&0xFF) + ((color>>8)&0xFF);
        blue = ((color_tmp>>0)&0xFF) + ((color>>0)&0xFF);
        color_tmp = (color>>24)&0xFF;
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, color,  color_tmp);
        color_tmp = (color_tmp<<8) + (red&0xFF);
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, red,  color_tmp);
        color_tmp = (color_tmp<<8) + (green&0xFF);
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, green,  color_tmp);
        color_tmp = (color_tmp<<8) + (blue&0xFF);
        //qDebug("[%s--%d] color[%08X %08X]", __func__, __LINE__, blue,  color_tmp);
        //qDebug("[%s--%d] color[%08X %08X %08X] rgb[%04X %04X %04X] _grayscale[%3d] \r\n", __func__, __LINE__, color, color2, color_tmp, red, green, blue, _grayscale);
        color = color_tmp;
    }
    else // color --
    {
        if(_grayscale>=scale_len) _grayscale=scale_len-1;
        if(_grayscale<0) _grayscale=0;
        color_tmp = rgb_mixture(color, 0x00000000, scale[_grayscale]);
        _grayscale --;
        if(_grayscale<=0) { _mode=0; _grayscale=0; ret = 0; }
        red = ((color_tmp>>16)&0xFF) + ((color2>>16)&0xFF);
        green = ((color_tmp>>8)&0xFF) + ((color2>>8)&0xFF);
        blue = ((color_tmp>>0)&0xFF) + ((color2>>0)&0xFF);
        color_tmp = (color>>24)&0xFF;
        color_tmp = (color_tmp<<8) + (red&0xFF);
        color_tmp = (color_tmp<<8) + (green&0xFF);
        color_tmp = (color_tmp<<8) + (blue&0xFF);
        color = color_tmp;
    }
#endif
    return ret;
}

void Bar_Palette_Init(const uint8_t scale[], const uint8_t scale_len, uint32_t bar[128], int16_t &bar_len)
{
    const uint32_t Bar_Palette[3] = {COLOR_RGB_RED, COLOR_RGB_GREEN, COLOR_RGB_BLUE};
    const int16_t Bar_Len = 3;
//    const uint8_t scale[] = {0, 45, 85, 170, 210, 255};
//    const uint8_t scale_len = sizeof(scale);
    int index;
    uint32_t color, color2;
    int16_t cIndex, _cIndex;
    int16_t gray2=0;
    uint8_t gray2_mode=0;
    cIndex=0;
    //_cIndex=0;
    gray2 = 0;//gray;
    gray2_mode = 0;//gray_mode;
    bar_len =48;
    for(index=0; index<128; index++)
    {
        color = Bar_Palette[cIndex];
        _cIndex=cIndex+1;
        if(_cIndex>=Bar_Len) _cIndex=0;
        if(_cIndex<0) _cIndex=Bar_Len-1;
        color2 = Bar_Palette[_cIndex];
        //color = rgb_mixture(color, color2, scale[gray2]);
        //color = rgb_mixture(color, color2, gray2);
        //color = rgb_mixture(color2, color, gray2);
        //color = rgb2grb(color, Draw.Grayscale);
        //bar[index] = color;
        //qDebug("[%s--%d] Palette[%08X %08X] bar[%3d]:%08X, scale[%2d]:%3d", __func__, __LINE__, Palette[cIndex]&0xFFFFFFFF, Palette[_cIndex]&0xFFFFFFFF, index, bar[index], gray2, scale[gray2]);
        //qDebug("[%s--%d] Palette[%08X %08X] bar[%3d]:%08X, scale[%2d %3d]", __func__, __LINE__, Palette[cIndex]&0xFFFFFFFF, Palette[_cIndex]&0xFFFFFFFF, index, bar[index], gray, gray2);
        //gray2++;
        //if(sizeof(scale)<=gray2)
        //if(0==grayGradual(gray2, gray2_mode, 0, 255, 32))
        if(0==color_to_color2(scale, scale_len, gray2, gray2_mode, 0, 255, 32, color, color2))
        {
            //qDebug("[%s--%d] Palette[%08X %08X] bar[%3d]:%08X, scale[%2d %3d]", __func__, __LINE__, Palette[cIndex]&0xFFFFFFFF, Palette[_cIndex]&0xFFFFFFFF, index, color, gray2_mode, gray2);
            //gray2=1;
            cIndex++;
            if(cIndex>=Bar_Len) cIndex=0;
            if(cIndex<0) cIndex=Bar_Len-1;
        }
        //else qDebug("[%s--%d] Palette[%08X %08X] bar[%3d]:%08X, scale[%2d %3d]", __func__, __LINE__, Palette[cIndex]&0xFFFFFFFF, Palette[_cIndex]&0xFFFFFFFF, index, color, gray2_mode, gray2);
        if((0!=index) && (color==bar[0]))
        {
            bar_len = index;
            break;
        }
        bar[index] = color;
    }
}

//static const uint8_t scale[] = {0, 64, 128, 192, 255};
static const uint8_t scale[] = {0, 64, 160, 255};
//static const uint8_t scale[] = {0, 170, 255};
static uint32_t bar[128] = {0xFF0000, };
static int16_t bar_len;

struct cledMatrixParams mParams;
//cledMatrix::cledMatrix()
void cledMatrixInit(void)
{
    ugui_init();
    Bar_Palette_Init(scale, sizeof(scale), bar, bar_len);
    UG_DrawLine(0, 0, 200, 200, bar[0]);
    //UG_FillCircle( 100, 100, 50, bar[5]);
    //UG_PutString( 20, 20, "Hello");
    UG_DrawCircle(20, 21, 20, COLOR_RGB_GREEN);
    UG_DrawCircle(20, 41, 20, COLOR_RGB_GREEN);
    mParams.time = 1000.0;
    mParams.FPS = 60;
    mParams.Speed = 100;
    mParams.Slider2Val = 50;
}
//static double time = 1000.0;
//static unsigned int FPS = 60;
//static unsigned int Speed = 100;
//static unsigned int Slider2Val = 50;

//static unsigned int shape = 1;
//static double progress = 0.f;
